/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	File:		GlbSemaTest.cpp			*/
/********************************************************/

#include "GlbSema.h"
#include "GlbThread.h"

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

using namespace GlbCls;

void* GlbSemaCoreInit(void* pPara)
{
	int iValue = 0;
	char* pszCur = NULL;
	char szBuffer[GLB_PACKET] = { 0 };
	GlbCls::CGlbSema* pCSema = (GlbCls::CGlbSema*)pPara;

	while (GLB_FAILURE == pCSema->GlbSemaWait()) {}

	pszCur = szBuffer;
	pCSema->GlbSemaGetValue(iValue);
	sprintf(szBuffer, "I am thread[%lu] value[%d], hello world!\n", pthread_self(), iValue);

	while ('\0' != *pszCur) {
		fputc(*pszCur ++, stderr);
		usleep(25000);
	}

	pCSema->GlbSemaPost();

	pthread_exit(NULL);
}

void GlbSemaRunInit()
{
	int iCount = 0;
	int iTotal = 5;
	GlbCls::CGlbSema CSema;
	GlbCls::CGlbThread* pCThread = new GlbCls::CGlbThread[iTotal];

	if (GLB_SUCCESS == CSema.GlbSemaInit(0, 1)) {
		for (iCount = 0; iCount < iTotal; iCount ++) {
			(pCThread + iCount)->GlbThreadAttrInit();
			(pCThread + iCount)->GlbThreadRoutineSet(GlbSemaCoreInit);
			(pCThread + iCount)->GlbThreadCreate(&CSema);
		}
		for (iCount = 0; iCount < iTotal; iCount ++) {
			(pCThread + iCount)->GlbThreadJoin(NULL);
		}
		CSema.GlbSemaDestroy();
	}
	else {
		GLB_ERROR("Failed to GlbSemaInit\n");
	}

	return;
}

void GlbSemaCoreOpen()
{
	int iValue = 0;
	char* pszCur = NULL;
	GlbCls::CGlbSema CSema;
	char szBuffer[GLB_PACKET] = { 0 };

	if (GLB_SUCCESS == CSema.GlbSemaOpen((char*)"GlbSemaTest", 1)) {
		while (GLB_FAILURE == CSema.GlbSemaWait()) {}

		pszCur = szBuffer;
		CSema.GlbSemaGetValue(iValue);
		sprintf(szBuffer, "I am process[%d] value[%d], hello world!\n", getpid(), iValue);

		while ('\0' != *pszCur) {
			fputc(*pszCur ++, stderr);
			usleep(25000);
		}

		CSema.GlbSemaPost();
	}
	else {
		GLB_ERROR("Failed to GlbSemaOpen\n");
	}

	return;
}

void GlbSemaRunOpen()
{
	pid_t iPid = 0;
	UINT uiCount = 0;
	UINT uiTotal = 5;
	GlbCls::CGlbSema CSema;

	CSema.GlbSemaUnlink((char*)"GlbSemaTest");

	for (; uiCount < uiTotal; uiCount ++) {
		switch ((iPid = fork())) {
			case GLB_SUCCESS:
				/* child */
				GlbSemaCoreOpen();
				exit(GLB_SUCCESS);
				break;
			case GLB_FAILURE:
				/* error */
				GLB_ERROR("%s\n", strerror(errno));
				break;
			default:
				/* parent */
				break;
		}
	}

	return;
}

int main(int argc, char* argv[])
{
	if (argc > 1) {
		GlbSemaRunInit();
	}
	else {
		GlbSemaRunOpen();
	}

	return GLB_SUCCESS;
}
